package com.apache.ius.controller;

import com.apache.api.api.ApiService;
import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.cache.service.CacheManager;
import com.apache.cache.service.impl.LoadCacheFactory;
import com.apache.cache.service.impl.redis.RedisCoreFactory;
import com.apache.cache.util.Validator;
import com.apache.database.constant.SpringContextLoader;
import com.apache.database.constant.SystemTools;
import com.apache.exception.BusinessException;
import com.apache.ius.able.CacheHelper;
import com.apache.ius.common.CommonUtils;
import com.apache.ius.plugin.InitCacheDataUtil;
import com.apache.ius.plugin.IusPluginUtil;
import com.apache.rpc.common.LoadRpcService;
import com.apache.rpc.entity.InterfaceRegister;
import com.apache.rpc.entity.RpcDatasource;
import com.apache.tools.ConfigUtil;
import com.apache.tools.DataMap;
import com.apache.tools.StrUtil;
import com.apache.uct.common.ToolsUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;

/**
 * description:缓存操作接口（根据ius参数加载数据，对缓存内数据进行操作）
 * @author xhe 创建时间：2019年03月26日
 */
@Controller
@RequestMapping({"/iusCache"})
public class IusCacheAction extends BaseAction{

    protected Logger log = Logger.getLogger(getClass());

    @Autowired(required = false)
    @Qualifier("infoService")
    private ApiService infoService;

    /**
     * 查看缓存内容
     */
    @RequestMapping(value = "/view", method = RequestMethod.GET)
    @ResponseBody
    public Object view(HttpServletRequest request)throws IOException, ServletException {
        Map<String, String> paramMap = getParameterMap(request);
        log.info("view cache request paramMap->"+paramMap);
        String cacheSpaceName = StrUtil.doNull( paramMap.get("cacheSpaceName"),"");
        String cachekey = paramMap.get("cachekey");

        Map<String, Object> returnData = new HashMap<String, Object>();
        if (Validator.isNull(cachekey)) {
            returnData.put("flag", "F");
            returnData.put("msg", "缺少缓存参数");
            return  returnData;
        }
        Object obj = LoadCacheFactory.getInstance().getCacheManager(cacheSpaceName).getCacheObjectByKey(cachekey);
        String resultStr = "暂无数据";
        if(obj!=null){
            if(obj instanceof String){
                resultStr = obj.toString();
            }else if(obj instanceof List){
                resultStr = JSONArray.fromObject(obj).toString();
            }else{
                resultStr = JSONObject.fromObject(obj).toString();
            }
        }
        log.info("view cache->"+resultStr);
        returnData.put("flag", "T");
        returnData.put("msg",resultStr);
        return returnData;
    }

    /**
     * 初始化添加缓存
     */
    @RequestMapping(value = "/init", method = RequestMethod.POST)
    @ResponseBody
    public Object init(HttpServletRequest request)throws IOException, ServletException {
        Map<String, Object> returnData = new HashMap<String, Object>();
        returnData.put("flag", "F");
        Map<String, String> paramMap = getParameterMap(request);
        log.info("init cache request paramMap->"+paramMap);

        //1、从缓存中获取ius配置的接口信息
        String formName = paramMap.get("formName");
        String pageName = paramMap.get("pageName");
        if(Validator.isNull(formName) || Validator.isNull(pageName)){
            returnData.put("msg", "缺少缓存参数");
            return returnData;
        }
        String cache_key = formName + "_" + pageName;
        Object cache_result = LoadCacheFactory.getInstance().getCacheManager("iusparamcache").getCacheObjectByKey(cache_key);
        if(Validator.isEmpty(cache_result)){
            returnData.put("msg", "未找到接口参数配置："+cache_key);
            return returnData;
        }

        //2、执行ius相关接口配置的查询信息
        //System.out.println(JSONObject.fromObject(cache_result));
        Map dMap = (Map)cache_result;
        String searchObjName = String.valueOf(dMap.get("modelTypes"));
        String datasource = String.valueOf(dMap.get("sysName"));
        String sysEname = StrUtil.doNull(CommonUtils.getSysEname(),datasource);
        String tableObjName = searchObjName.split(",")[0].split("_")[1];//得到表对象
        if("sortInfo".equals(tableObjName)){
            sysEname = paramMap.get("sortInfo.w_sysName");
            ParamsVo psvo = new ParamsVo();
            psvo.setMethodKey("metadataAction");
            psvo.setParams("method","initCache");
            psvo.setParams("sysPass",paramMap.get("sysPass"));
            psvo.setParams("sysName", sysEname);
            log.info("系统["+sysEname+"]下所有[数据表信息]到缓存中...start !");
            doInfoService(psvo);
        }else{
            Map<String, Object> whereMap = new HashMap<String,Object>();
            whereMap.putAll(paramMap);
            whereMap.remove("page");
            whereMap.remove("row");
            whereMap.remove("pageName");
            whereMap.remove("formName");
            whereMap.remove("sysPass");
            whereMap.remove("Client-IP");
            //执行数据查询，封装对象查询属性条件
            for (String attrKey : paramMap.keySet()) {
                if(attrKey.indexOf(tableObjName)>-1){
                    whereMap.put(attrKey,paramMap.get(attrKey));
                }
            }
            ResultEntity resultEntity = IusPluginUtil.getInstance().select(datasource,"list",searchObjName,whereMap);
            if (Validator.isEmpty(resultEntity.getEntity())){
                returnData.put("msg", "未找到接口数据："+whereMap);
                return returnData;
            }
            List<DataMap> dataList = (List<DataMap>)resultEntity.getEntity();

            //3、判断是否特殊表，部分特殊表则需要封装实体方法个性处理
            if("tInterfaceRegister".equals(tableObjName)){
                String beanId = StrUtil.doNull(paramMap.get("tInterfaceRegister.w_beanId"),paramMap.get("tInterfaceRegister.wi_beanId"));
                String cache_spaceName = "apachecache";
                log.info("系统["+beanId+"]下所有[RPC接口]缓存加载...start !");
                if(StrUtil.isNull(beanId)){
                    returnData.put("msg", "beanId不能为空！");
                    return returnData;
                }
                String [] beanIdArray = new String[]{beanId};
                if(beanId.indexOf(",")>0){
                    beanIdArray = beanId.split(",");
                }
                for (String k : beanIdArray){
                    initInterface(k,dataList,cache_spaceName);
                }
            }else if("tRpcDatasource".equals(tableObjName)){
                String cache_spaceName = "apachecache";
                sysEname = paramMap.get("tRpcDatasource.w_sysEname");
                log.info("系统["+sysEname+"]下所有[数据源接口]缓存加载...start !");
                if(StrUtil.isNull(sysEname)){
                    log.error("initDataSource.缺少参数：tRpcDatasource.w_sysEname");
                }else{
                    initDataSource(sysEname,dataList,cache_spaceName);
                }
            }else if("sysParamManager".equals(tableObjName)){
                log.info("系统["+sysEname+"]下所有[IUS接口参数]缓存加载...start !");
                initIusParams(dataList);
            }else if("sysPluginGroup".equals(tableObjName)){
                log.info("系统["+sysEname+"]下所有[插件组合]缓存加载...start !");
                initSysPluginGroup(dataList);
            }else if("sysPluginManager".equals(tableObjName)){
                log.info("系统["+sysEname+"]下所有[插件定义]缓存加载...start !");
                initSysPluginManager(dataList);
            }else if("sysVersion".equals(tableObjName)){
                log.info("系统["+sysEname+"]下所有[接口版本]缓存加载...start !");
                initVersion(dataList);
            }else{
                String sysNameParamName = tableObjName+".w_sysName";
                if(paramMap.containsKey(sysNameParamName)){
                    sysEname = paramMap.get(sysNameParamName);
                }else{
                    if(StrUtil.isNull(sysEname)){
                        if(paramMap.containsKey(tableObjName+".sysName")){
                            sysEname = paramMap.get(tableObjName+".sysName");
                        }
                    }
                    if(StrUtil.isNull(sysEname)) {
                        if (paramMap.containsKey("sysName")) {
                            sysEname = paramMap.get("sysName");
                        }
                    }
                    sysEname = "";
                }
                try{
                    InitCacheDataUtil.getInstance().initDataToCacheOther(sysEname,tableObjName,dataList,paramMap);
                }catch (BusinessException be){
                    returnData.put("flag", "F");
                    returnData.put("msg", be.getMessage());
                    return returnData;
                }
            }
        }
        returnData.put("flag", "T");
        returnData.put("msg", "缓存更新成功");
        return returnData;
    }

    /**
     * IUS参数缓存同步
     */
    public void initIusParams(List dataList) {
        if(Validator.isEmpty(dataList))
            return;
        if (!ToolsUtil.isEmpty(dataList)) {
            int count = dataList.size();
            for (int i = 0; i < dataList.size(); i++) {
                Map map = (Map) dataList.get(i);
                String key = map.get("formName") + "_" + map.get("pageName");
                CacheHelper.getInstance().setIusParamCache(key, map);
            }
            log.info("初始化[IUS接口参数]["+count+"]条数据到缓存完成！");
        }
    }

    /**
     * 初始化 InterfaceRegister
     */
    private void initInterface(String beanId,List<DataMap> dataList,String cache_spaceName){
        String cache_key = "interfaceRegister_" + beanId;
        log.info("接口注册信息加载start->"+cache_key);
        if(dataList.size()>0){
            List<InterfaceRegister> vos = (List) SystemTools.getInstance().getCache(cache_spaceName).getCacheObjectByKey(cache_key);
            if (Validator.isEmpty(vos)) {
                vos = new ArrayList<InterfaceRegister>();
            }

            for(int i=0;i<dataList.size();i++){
                DataMap dmObj = dataList.get(i);

                InterfaceRegister register = new InterfaceRegister();
                register.setRegisterId(String.valueOf(dmObj.get("registerId")));
                String data_beanId = String.valueOf(dmObj.get("beanId"));
                if(!data_beanId.equals(beanId)){
                    continue;
                }
                register.setBeanId(data_beanId);
                register.setBeanName(String.valueOf(dmObj.get("beanName")));
                register.setAddress(String.valueOf(dmObj.get("address")));
                register.setPort(String.valueOf(dmObj.get("port")));
                register.setMethodName(String.valueOf(dmObj.get("methodName")));
                register.setCallType(String.valueOf(dmObj.get("callType")));
                register.setFlag(String.valueOf(dmObj.get("flag")));
                register.setReserve1(String.valueOf(dmObj.get("reserve1")));
                register.setReserve2(String.valueOf(dmObj.get("reserve2")));
                register.setTimestampCreate(Long.parseLong(String.valueOf(dmObj.get("timestampCreate"))));
                register.setUserIdCreate(String.valueOf(dmObj.get("userIdCreate")));

                Iterator<InterfaceRegister> iterator = vos.iterator();
                while(iterator.hasNext()){
                    InterfaceRegister ifr = iterator.next();
                    if (ifr.getRegisterId().equals(register.getRegisterId())) {
                        iterator.remove();
                    }
                }
//
//                for (InterfaceRegister ifr : vos) {
//                    if (ifr.getRegisterId().equals(register.getRegisterId())) {
//                        vos.remove(ifr);
//                        break;
//                    }
//                }
                vos.add(register);
                log.info((i+1)+"）接口注册对象->"+ JSONObject.fromObject(register).toString());
            }

            SystemTools.getInstance().getCache(cache_spaceName).createCacheObject(cache_key, vos);
            log.info("初始化[接口注册信息]["+cache_key+"]["+vos.size()+"]条数据到缓存完成！");
        }else{
            SystemTools.getInstance().getCache(cache_spaceName).removeCacheObject(cache_key);
            log.info("暂无【启用】状态的接口，故不加载缓存！");
        }
    }

    /**
     * 初始化 rpc_datasource
     */
    private void initDataSource(String sysEname,List<DataMap> dataList,String cache_spaceName){
        if(dataList.size()>0){
            String cache_key = "rpc_datasource_" + sysEname;
            DataMap dmObj = dataList.get(0);
            RpcDatasource rds = new RpcDatasource();

            rds.setDataName(String.valueOf(dmObj.get("dataName")));
            rds.setDatabaseType(String.valueOf(dmObj.get("databaseType")));
            rds.setSysEname(String.valueOf(dmObj.get("sysEname")));
            rds.setDriverClassName(String.valueOf(dmObj.get("driverClassName")));
            rds.setJdbcPassword(String.valueOf(dmObj.get("jdbcPassword")));
            rds.setJdbcUrl(String.valueOf(dmObj.get("jdbcUrl")));
            rds.setJdbcUsername(String.valueOf(dmObj.get("jdbcUsername")));
            rds.setDatasource1(String.valueOf(dmObj.get("datasource1")));
            rds.setDatasource2(String.valueOf(dmObj.get("datasource2")));
            SystemTools.getInstance().getCache(cache_spaceName).createCacheObject(cache_key, rds);

            String cacheKeys = "rpc_datasource_keys";
            String cacheKeys_values = String.valueOf(SystemTools.getInstance().getCache(cache_spaceName).getCacheObjectByKey(cacheKeys));
            cacheKeys_values = Validator.getDefaultStr(cacheKeys_values, "");
            if(cacheKeys_values.indexOf(sysEname)==-1){
                if (!cacheKeys_values.endsWith(",")){
                    cacheKeys_values+=",";
                }
                cacheKeys_values+=sysEname;
                SystemTools.getInstance().getCache(cache_spaceName).createCacheObject(cacheKeys, cacheKeys_values);
                log.info("更新[数据源信息]["+cacheKeys+"->"+cacheKeys_values+"]到缓存");
            }
            log.info("更新[数据源信息]["+cache_key+"]到缓存完成！");
        }
    }


    /**
     * IUS插件缓存同步
     */
    public void initSysPluginManager(List dataList) {
        String cache_spaceName="pluginsCache";
        if(Validator.isEmpty(dataList))
            return;
        if (!ToolsUtil.isEmpty(dataList)) {
            int count = dataList.size();
            for (int i = 0; i < dataList.size(); i++) {
                Map map = (Map) dataList.get(i);
                String key = "group_" + String.valueOf(map.get("pluginShortName"));
                String value = String.valueOf(map.get("pluginFullName"));
                SystemTools.getInstance().getCache(cache_spaceName).createCacheObject(key, value);
                log.info((i+1)+".["+key+"]["+value+"] "+String.valueOf(map.get("pluginRemark")));
            }
            log.info("更新[插件]["+count+"]条数据到缓存完成！");
        }
    }

    /**
     * IUS插件组合缓存同步
     */
    public void initSysPluginGroup(List dataList) {
        String cache_spaceName="pluginsCache";
        if(Validator.isEmpty(dataList))
            return;
        if (!ToolsUtil.isEmpty(dataList)) {
            int count = dataList.size();
            for (int i = 0; i < dataList.size(); i++) {
                Map map = (Map) dataList.get(i);
                String key = "plugin_" + String.valueOf(map.get("rulesCode"));
                String value = String.valueOf(map.get("rulesName"));
                SystemTools.getInstance().getCache(cache_spaceName).createCacheObject(key, value);
                log.info((i+1)+".["+key+"]["+value+"] "+String.valueOf(map.get("rulesRemark")));
            }
            log.info("更新[插件组合]["+count+"]条数据到缓存完成！");
        }
    }
    /**
     * IUS版本号缓存同步
     */
    public void initVersion(List dataList) {
        String cache_spaceName="versionCache";
        if(Validator.isEmpty(dataList))
            return;
        if (!ToolsUtil.isEmpty(dataList)) {
            RedisCoreFactory.getInstance().getJedis().del(cache_spaceName);
            int count = dataList.size();
            for (int i = 0; i < dataList.size(); i++) {
                Map map = (Map) dataList.get(i);
                String status = String.valueOf(map.get("status"));
                if("1".equals(status)){//当前版本
                    SystemTools.getInstance().getCache(cache_spaceName).createCacheObject("current_version", String.valueOf(map.get("versionNo")));
                }
                String key = "version_" + String.valueOf(map.get("versionNo"));
                SystemTools.getInstance().getCache(cache_spaceName).createCacheObject(key, map);
                log.info((i+1)+".["+key+"]["+map+"] ");
            }
            log.info("更新[插件]["+count+"]条数据到缓存完成！");
        }
    }

    private Map<String,Object> getCacheObjTypeMap(){
        Map<String,Object> cacheObjTypeMap = new HashMap<String,Object>();

        //tInterfaceRegister-->InterfaceRegister
        JSONObject jsonObject_interFace=new JSONObject();
        jsonObject_interFace.put("cacheSpaceName","apachecache");
        jsonObject_interFace.put("dataObj",new InterfaceRegister());
        cacheObjTypeMap.put("tInterfaceRegister",jsonObject_interFace);

        //tRpcDatasource-->RpcDatasource
        JSONObject jsonObject_rpcDatasource=new JSONObject();
        jsonObject_rpcDatasource.put("cacheSpaceName","apachecache");
        jsonObject_rpcDatasource.put("dataObj",new RpcDatasource());
        cacheObjTypeMap.put("tRpcDatasource",jsonObject_rpcDatasource);

        //tRpcDatasource-->RpcDatasource
        JSONObject jsonObject_iusParam=new JSONObject();
        jsonObject_iusParam.put("cacheSpaceName","iusparamcache");
        jsonObject_iusParam.put("dataObj",new DataMap());
        cacheObjTypeMap.put("sysParamManager",jsonObject_iusParam);

        return cacheObjTypeMap;
    }

    public void setInfoService(ApiService infoService) {
        this.infoService = infoService;
    }

    protected ResultEntity doInfoService(ParamsVo vo){
        if(null == this.infoService) {
            Object obj = SpringContextLoader.getBean("infoService");
            if (obj != null) {
                this.infoService = (ApiService) obj;
            }
        }
        if(null == this.infoService){
            return LoadRpcService.service().doService("infoService",vo.getMethodKey(),"xml",vo.getParams(),null);
        }else{
            return this.infoService.doService(vo);
        }
    }

}
